package com.huarui.receive.service;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONNull;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.ewaf.framework.model.ListModel;
import org.ewaf.framework.service.BaseService;
import org.ewaf.framework.task.Engine;
import org.ewaf.framework.task.EngineAccess;
import org.ewaf.framework.task.Handler;
import org.ewaf.framework.util.BeanUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.huarui.button.EngineTypeEnum;
import com.huarui.code.dao.ICodeGenericDao;
import com.huarui.code.model.CodeGeneric;
import com.huarui.dictionary.DictionaryEnum;
import com.huarui.inventory.dao.IInventoryDao;
import com.huarui.inventory.model.Inventory;
import com.huarui.part.dao.IPartDao;
import com.huarui.partner.dao.IPartnerDao;
import com.huarui.partner.model.Partner;
import com.huarui.payable.dao.IPayableDao;
import com.huarui.payable.model.Payable;
import com.huarui.purchaseOrder.dao.IPurchaseOrderDao;
import com.huarui.purchaseOrder.dao.IPurchaseOrderDetailDao;
import com.huarui.purchaseOrder.model.PurOrSaleOrder;
import com.huarui.quotation.service.QuotationService;
import com.huarui.receive.dao.IReceiveDao;
import com.huarui.receive.dao.IReceiveItemDao;
import com.huarui.receive.model.Receive;
import com.huarui.receive.model.ReceiveButtonEnum;
import com.huarui.receive.model.ReceiveItem;
import com.huarui.receive.model.ReceiveModel;

import com.huarui.user.dao.IUserDao;
import com.huarui.user.model.SessionMessage;
import com.huarui.user.model.User;
import com.huarui.user.security.UserHolder;
import com.huarui.util.ConstantUtil;
import com.huarui.util.JsonUtil;

public class ReceiveService extends BaseService {

	private IReceiveItemDao receiveItemDao;
    private IInventoryDao inventoryDao;   
    private IPartnerDao partnerDao;
    private IPayableDao payableDao;
    private IPurchaseOrderDao purchaseOrderDao;
    private ICodeGenericDao codeGenericDao;
	private IPurchaseOrderDetailDao purchaseOrderDetailDao;
	private IUserDao userDao;
	private EngineAccess engineAccess;
	private IPartDao partDao;
	private TransactionTemplate transactionTemplate;
	private QuotationService quotationService;

	private IReceiveDao getDao() {
		return (IReceiveDao) dao;
	}	

	public void createReceiveItem(ReceiveItem receiveItem) {

		receiveItemDao.create(receiveItem);
	}

	public void UpdateReceiveItem(ReceiveItem receiveItem) {

		receiveItemDao.update(receiveItem);

	}
	/**
	 * 根据id,buyerId获得Receive
	 * @param id
	 * @return Receive
	 */
	public Receive getRceiveById(Integer id,boolean update){
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(ConstantUtil.UPDATE, update);
		map.put(ConstantUtil.PARAM_OF_ID, id);
		map.put(ConstantUtil.PARAM_OF_BUYERID, UserHolder.getCurrentSessionMessage().getCompanyId());
		return getDao().getReceiveById(map);
	}
	/**
	 * 根据id,buyerId删除Receive
	 * @param id
	 * @return
	 */
	public boolean deleteReceiveByReceiveId(Integer id){
		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put(ConstantUtil.PARAM_OF_ID, id);
		map.put(ConstantUtil.PARAM_OF_BUYERID, UserHolder.getCurrentSessionMessage().getCompanyId());
		return getDao().deleteReceiveById(map);
	}
	
	public ReceiveItem getReceiveItemByOrdersItemId(Integer ordersItemId) {
		return receiveItemDao.getReceiveItemByOrdersItemId(ordersItemId);
	}

	public List<Map<String,String>> getReceiveItemByReceiveId(Integer receiveId) {
		return receiveItemDao.getReceiveItemByReceiveId(receiveId);
	}
	/**
	 * 接手或释放单据产生新的按钮
	 * @param receiveId
	 * @param type
	 * @return {"isOwner":xxxxx,"buttons":[{xxxx},{xxxx}...],'success':true} 
	 */
	public JSONObject updateReceiveCurrentorIdById(Integer receiveId,Integer userId){
		SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		Map<String,Object> map = new HashMap<String,Object>();
		map.put(ConstantUtil.PARAM_OF_ID, receiveId);
		map.put(ConstantUtil.PARAM_OF_CURRENTORID, userId);
		map.put(ConstantUtil.PARAM_OF_BUYERID, sessionMessage.getCompanyId());
		getDao().updateReceiveCurrentorId(map);
		Receive receive = getRceiveById(receiveId, false);
		JSONObject buttonObj = generateButtonsByStatus(receive.getStatus(), receive.getCurrentorId(), sessionMessage.getUserId());
		buttonObj.put(ConstantUtil.SUCCESS, true);
		return  buttonObj;
	}
    /**
     * 待入库状态下根据入库单id,将单据退回草稿状态
     * @param receiveId
     * @return  {'success':true,'main':{xxxx},'details':[{xxx},{xxxxx}...],'buttons':{'isOwner':true/false,'buttons':[{xxxx},{xxxx}...]},'msg':{'confirm'/'alert':xxxxx}} or {"success":false,"msg":'XXXXX'}
     */
	public JSONObject updateReceiveStatusById(final Integer receiveId) {
		final SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		Object result = transactionTemplate.execute(new TransactionCallback() {			
			@Override
			public Object doInTransaction(TransactionStatus status) {	
				/**
				 * TODO : select for update
				 */
				Receive receive = getRceiveById(receiveId,true);
				JSONObject response = checkCurrentorIdBeforeUpdate(sessionMessage, receive);
				if(response != null){
					return response;
				}else{
					receive.setStatus(Receive.STATUS_DRAFT);
					receive.setSubmitter(null);
					receive.setGmtSubmit(null);
					getDao().update(receive);
					JSONObject responseObject = getReceiveAndItemsById(receiveId, sessionMessage);
					responseObject.put(ConstantUtil.MSG,ConstantUtil.BACK_TO_DRAFT_SUCCESS);					
					responseObject.put(ConstantUtil.SUCCESS, true);
				    return responseObject;
				}
			}
		});
		return (JSONObject) result;		
	}
	
	
    /**
     * 根据条件查询Receive
     * @param queryMap
     * @return List<ReceiveModel>
     */
	@SuppressWarnings("unchecked")
	public List<ReceiveModel> getReceiveByConditons(Map queryMap) {

		return getDao().getReceiveByConditons(queryMap);
	}
	/**
	 * 根据条件查询符合的Receive记录数
	 * @param queryMap
	 * @return Integer
	 */
	@SuppressWarnings("unchecked")
	public Integer getReceiveCountByConditons(Map queryMap) {
		return getDao().getReceiveCountByConditons(queryMap);
	}
	
	/**
	 * 根据订单id,拥有者id，varGroup查询Receive
	 * @param orderId
	 * @param varGroup
	 * @return ReceiveModel
	 */
	@SuppressWarnings("unchecked")
	public ReceiveModel getReceiveByOrdersId(Integer orderId, String varGroup) {
		Map queryMap = new HashMap();
		queryMap.put(ConstantUtil.PARAM_OF_COMPANYID, UserHolder.getCurrentSessionMessage().getCompanyId());
		queryMap.put(ConstantUtil.PARAM_OF_ORDERSID, orderId);
		queryMap.put(ConstantUtil.PARAM_OF_VARGROUP, varGroup);
		List<ReceiveModel> ml = getDao().getReceiveByConditons(queryMap);
		return  ml.size() > 0 ? ml.get(0):null;
	}

	/**
	 * 获得Receive的分页模型
	 * @param queryMap
	 * @param lm
	 * @param sessionMessage
	 * @return ListModel
	 */

	@SuppressWarnings("unchecked")
	public ListModel getReceiveListModelByConditons(Map queryMap, ListModel lm,SessionMessage sessionMessage) {
		queryMap.put(ConstantUtil.PARAM_OF_VARGROUP, DictionaryEnum.GROUP_RECEIVE_STATUS.getGroup());
		queryMap.put(ConstantUtil.PARAM_OF_COMPANYID, sessionMessage.getCompanyId());
		lm.setTotal(getDao().getReceiveCountByConditons(queryMap));
		if(lm.getOrderBy()==null){
			lm.setOrderBy(ConstantUtil.ORDERBY_GMTCREATE);
		}
		queryMap.put(ConstantUtil.PARAM_OF_LISTMODEL, lm);
		List<ReceiveModel> reList = getDao().getReceiveByConditons(queryMap);		
		lm.setResult(reList);
		return lm;
	}
	/**
	 * 查询入库明细及相应库存信息,以Map形式返回结果
	 * @param map
	 * @param sessionMessage
	 * @return List<Map>
	 */
	@SuppressWarnings("unchecked")
	public List<Map> getReceiveItemByConditonsWithInventory(Map map,SessionMessage  sessionMessage){
		map.put(ConstantUtil.PARAM_OF_WITHINVENTORY, true);
		map.put(ConstantUtil.PARAM_OF_COMPANYID, sessionMessage.getCompanyId());
		return receiveItemDao.getReceiveItemByConditons(map);
	}
	
	@SuppressWarnings("unchecked")
	public ListModel getReceiveItemByConditons(Map map, ListModel lm,SessionMessage sessionMessage) {
		map.put(ConstantUtil.PARAM_OF_COMPANYID, sessionMessage.getCompanyId());
		lm.setTotal(receiveItemDao.getReceiveItemCountByConditions(map));
		if(lm.getOrderBy()==null){
			lm.setOrderBy(ConstantUtil.ORDERBY_CODEOFBUYER);
		}
		map.put(ConstantUtil.PARAM_OF_LISTMODEL, lm);
		List<Map> result = receiveItemDao.getReceiveItemByConditons(map);
		lm.setResult(result);
		return lm;
	}
	/**
	 * 根据id查询入库单主表，明细表
	 * @param id
	 * @param sessionMessage
	 * @return receiveJson:{'main':{xxxx},'details':[{xxx},{xxxxx}...],'buttons':{'isOwner':true/false,'buttons':[{xxxx},{xxxx}...]}}
	 */
	public JSONObject getReceiveAndItemsById(Integer id,SessionMessage sessionMessage){
		Map<String,Object> map = new HashMap<String,Object> ();
		map.put(ConstantUtil.PARAM_OF_ID, id);
		map.put(ConstantUtil.PARAM_OF_VARGROUP,DictionaryEnum.GROUP_RECEIVE_STATUS.getGroup());
		map.put(ConstantUtil.PARAM_OF_COMPANYID, sessionMessage.getCompanyId());	
		ReceiveModel receiveModel = getDao().getReceiveByConditons(map).get(0);		
		JSONObject mainJson = JsonUtil.getJSONObjectFromBean(receiveModel);		
		List<Map<String,String>> receiveItems = receiveItemDao.getReceiveItemByReceiveId(receiveModel.getId());
		JSONArray detailJson = JSONArray.fromObject(receiveItems);
		JSONObject buttonJson = generateButtonsByStatus(receiveModel.getStatus(), receiveModel.getCurrentorId(),sessionMessage.getUserId());
		JSONObject receiveJson = new JSONObject();
		receiveJson.put(ConstantUtil.JSON_OF_MAIN, mainJson);
		receiveJson.put(ConstantUtil.JSON_OF_DETAILS, detailJson);
		receiveJson.put(ConstantUtil.JSON_OF_BUTTONS, buttonJson);
		return receiveJson;
	}
	/**
	 * 根据订单号id查询订单主表及明细表	
	 * @param orderId
	 * @return  receiveJson:{'main':{xxxx},'details':[{xxx},{xxxxx}...],'buttons':{'isOwner':true/false,'buttons':[{xxxx},{xxxx}...]},'msg':{'confirm'/'alert':xxxxx}}
	 */
	@SuppressWarnings("unchecked")
	public JSONObject generateReceiveAndItemsByOrderId(Integer orderId) {
		SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		//主表
		JSONObject mainJson ;
		//明细表
		JSONArray detailJson;
		//相应按钮
		JSONObject buttonJson;
		
		JSONObject response = new JSONObject();
		
		ReceiveModel receive =getReceiveByOrdersId(orderId,DictionaryEnum.GROUP_RECEIVE_STATUS.getGroup());
		if (receive != null) {
			mainJson = JSONObject.fromObject(receive);
			// 取得入库单明细信息
			List<Map<String,String>> receiveItems = receiveItemDao.getReceiveItemByReceiveId( receive.getId());
			detailJson = JSONArray.fromObject(receiveItems);			
			// 根据订单状态及currentId获得相应的按钮
		   buttonJson = generateButtonsByStatus(receive.getStatus(),receive.getCurrentorId(),sessionMessage.getUserId());		   		  
		   response.put(ConstantUtil.JSON_OF_MAIN, mainJson);
		   response.put(ConstantUtil.JSON_OF_DETAILS, detailJson);
		   response.put(ConstantUtil.JSON_OF_BUTTONS, buttonJson);
		   response.put(ConstantUtil.HASRECEIVE, true);
		} else {
			// 采购订单未被处理过
			// 封装主表信息
			Map mainMap = purchaseOrderDao.getOrderByIdJson(orderId);
			/*mainJson = JSONObject.fromObject(mainMap);
			// 封装明细表信息
			List<Map<String, String>> detailMap = purchaseOrderDetailDao.getPurchaseOrderDetailByOrderIdJson(orderId);			
			detailJson = JSONArray.fromObject(detailMap);*/
			//获得相应的按钮	
			 //返回消息
			JSONObject msgObj = new JSONObject();
			String currentorName = (String) mainMap.get("currentorName");
			Integer currentorId = (Integer) mainMap.get("currentorId");
			Integer currentId = UserHolder.getCurrentSessionMessage().getUserId();	
			buttonJson=generateButtonsByStatus(Receive.STATUS_TO_CREATE,currentorId,sessionMessage.getUserId());
			if(currentorId == null || currentorId.equals(currentId)){
				msgObj.put(ConstantUtil.JSON_OF_CONFIRM, ConstantUtil.MSG_SURE_TO_CREATE);
			}else{
				String msg = currentorName+ConstantUtil.MSG_ALERT_TO_CREATE;
				msgObj.put(ConstantUtil.JSON_OF_CONFIRM, msg);
			}						
			response.put(ConstantUtil.MSG, msgObj);
			response.put(ConstantUtil.HASRECEIVE, false);
		}
		return response;
	}

	 /**
	    * 返回不同状态下的按钮条
	    * @param status
	    * @param currentorId
	    * @param userId
	    * @return  {"isOwner":xxxxx,"buttons":[{xxxx},{xxxx}...]}
	    */
		public JSONObject generateButtonsByStatus(String status,Integer currentorId, Integer userId) {
			//id，据此获得按钮
			String id;
			//判断单据所有者
			boolean isOwner = false;
			//按钮列表
			JSONArray buttonArray = null;					
			//判断是否当前所有者打开单据
			if(currentorId != null && currentorId.equals(userId)){	
				isOwner = true;
			}
			if(status.equals(Receive.STATUS_DRAFT)){
				if(isOwner){
					 id=ReceiveButtonEnum.STATUS_OF_DRAFTBYOWNER.getType();
					 buttonArray = getButtons(id);
					 
				}else{
					 id = ReceiveButtonEnum.STATUS_OF_DRAFTBYOTHER.getType();
					 buttonArray = getButtons(id);
				}
			}else if(status.equals(Receive.STATUS_TO_INVENTORY)){
				if(isOwner){
					id = ReceiveButtonEnum.STATUS_OF_TOINVENTORYBYOWNER.getType();
					buttonArray = getButtons(id);
				}else{
					id= ReceiveButtonEnum.STATUS_OF_TOINVENTORYBYOTHER.getType();
					buttonArray = getButtons(id);
				}
			}else if(status.equals(Receive.STATUS_INVENTORY)){
				id = ReceiveButtonEnum.STATUS_OF_INVENTORY.getType();
				buttonArray = getButtons(id);
			}else if(status.equals(Receive.STATUS_TO_CREATE)){
				id = ReceiveButtonEnum.STATUS_OF_TOCREATE.getType();
				buttonArray = getButtons(id);
			}
			JSONObject buttonObj = new JSONObject();
			buttonObj.put(ConstantUtil.JSON_OF_ISOWNER, isOwner);
			buttonObj.put(ConstantUtil.JSON_OF_BUTTONS, buttonArray);			
			return buttonObj;
		}
	    /**
	     * 根据状态获得按钮
	     * @param id
	     * @return
	     */
	    private JSONArray getButtons(String id) {
		    Engine engine = engineAccess.getEngine(EngineTypeEnum.ENGINE_TYPE_RECEIVE.getType());
		    List<Handler> handlers=engine.getHandlers(id);
		    JSONArray handlerObj = JSONArray.fromObject(handlers);	    		    
		    return handlerObj;
	    }
	/**
	 * 草稿状态下的操作
	 * @param queryParam
	 * @return  {'success':true,'receiveObject':{'main':{xxxx},'details':[{xxx},{xxxxx}...],'buttons':{'isOwner':true/false,'buttons':[{xxxx},{xxxx}...]},'msg':{'confirm'/'alert':xxxxx}}}
	 *  or {'success':false,'msg', '该订单已被'+xxxxxx+'成功处理!}'}";
	 */
	@SuppressWarnings("unchecked")
	public JSONObject backupDraft(String queryParam) {
		final JSONObject receiveObj = JSONObject.fromObject(queryParam);
		final SessionMessage sessionMessage =UserHolder.getCurrentSessionMessage();		
		Object result = transactionTemplate.execute(new TransactionCallback() {
			//主表
			Receive receive = generateReceive(receiveObj);
			//明细表
			Map receiveItemMap = generateReceiveItem(receiveObj);		
			//删除明细
			List<Integer> deleteItemIds = generateDeleteItemIds(receiveObj);
			//新增明细
			List<ReceiveItem> addItems = (List<ReceiveItem>) receiveItemMap.get(ConstantUtil.KEY_OF_ADDITEMS);		
			//修改明细
			 List<ReceiveItem> modifyItems = (List<ReceiveItem>) receiveItemMap.get(ConstantUtil.KEY_OF_MODIFYITEMS);
		    //总成本
			 BigDecimal amount = (BigDecimal) receiveItemMap.get(ConstantUtil.KEY_OF_AMOUNT);
			@Override
			public Object doInTransaction(TransactionStatus status) {
				JSONObject response=new JSONObject();
				receive.setAmount(amount);
				receive.setStatus(Receive.STATUS_DRAFT);				
				if (receive.getId() == null) {
					//首次操作该订单
					if(receive.getOrdersId()!=null){
						//判断此引用订单是否已被其他人处理完毕
						ReceiveModel receiveAlready = getReceiveByOrdersId(receive.getOrdersId(),DictionaryEnum.GROUP_RECEIVE_STATUS.getGroup());						
						if(receiveAlready !=null){
							//JSONObject response = getReceiveAndItemsById(receiveAlready.getId(), sessionMessage);
							response.put(ConstantUtil.SUCCESS, false);
							response.put(ConstantUtil.MSG, ConstantUtil.MSG_AHEAD+receiveAlready.getCreatorName()+ConstantUtil.MSG_ENDING);
							return response;
						}else{																			
							// 对新建的入库单，保存草稿，提交仓库，直接入库操作后清空orders的currentorId
							updatePurCurentorIdById(receive.getOrdersId());
						}
					}
					//保存
					insertReceiveDraft(sessionMessage, receive,false);										
				} else {
					response = checkCurrentorIdBeforeUpdate(sessionMessage, receive);
					if(response != null){
						return response;
					}
				    // 已保存的入库单,update操作:主表,明细表，删除被删除的记录
					getDao().update(receive);					
					if (modifyItems != null && modifyItems.size()>0){
						receiveItemDao.batchUpdateItems(modifyItems);
					}
					if (deleteItemIds != null && deleteItemIds.size()>0){
						batchDeleteItems(receive,deleteItemIds);
					}								
				}
				if (addItems != null && addItems.size()>0) {
					// 对新增的明细,不管入库单是否以创建，均为插入数据库
					addItems = setAddItemsReceiveId(addItems, receive);
					receiveItemDao.batchInsertItems(addItems);
				}
				//页面返回信息
				response = getReceiveAndItemsById(receive.getId(), sessionMessage);
				response.put(ConstantUtil.SUCCESS,true);
				response.put(ConstantUtil.MSG, ConstantUtil.SAVE_CREATE_SUCCESS);
				return response;
			}
			
		});		
		return (JSONObject) result;
	}
	
	
	private void insertReceiveDraft(SessionMessage sessionMessage,Receive receive,boolean isInventory) {
		String codeOfBuyer = codeGenericDao.getNewCode(sessionMessage.getCompanyId(), CodeGeneric.RECEIVE);
		receive.setCodeOfBuyer(codeOfBuyer);
		receive.setBuyerId(sessionMessage.getCompanyId());
		receive.setCreatorId(sessionMessage.getUserId());
		//receive.setGmtCreate(new Date());
		receive.setCurrentorId(sessionMessage.getUserId());
		if(isInventory){
			receive.setSubmitter(sessionMessage.getUserId());								
		}
		getDao().create(receive);
	}
	
	
	private void batchDeleteItems(Receive receive, List<Integer> deleteItemIds) {
		Map<String,Object> map = new HashMap<String, Object>();
		map.put(ConstantUtil.PARAM_OF_RECEIVEID, receive.getId());
		map.put(ConstantUtil.PARAM_OF_IDS, deleteItemIds);
		receiveItemDao.batchDeleteItems(map);
	}

	/**
	 * 提交仓库操作
	 * @param queryParam
	 * @return   {'success':true,'receiveObject':{'main':{xxxx},'details':[{xxx},{xxxxx}...],'buttons':{'isOwner':true/false,'buttons':[{xxxx},{xxxx}...]},'msg':{'confirm'/'alert':xxxxx}}}
	 *  "{'success':false,'errors':'发生异常'}";
	 */
	@SuppressWarnings("unchecked")
	public JSONObject backupToInventory(String queryParam){
		final JSONObject receiveObj = JSONObject.fromObject(queryParam);
		final SessionMessage sessionMessage =UserHolder.getCurrentSessionMessage();
		Object result = transactionTemplate.execute(new TransactionCallback() {						
			//主表
			Receive receive = generateReceive(receiveObj);
			//明细表
			Map receiveItemMap = generateReceiveItem(receiveObj);		
			//删除明细
			List<Integer> deleteItemIds = generateDeleteItemIds(receiveObj);
			//新增明细
			List<ReceiveItem> addItems = (List<ReceiveItem>) receiveItemMap.get(ConstantUtil.KEY_OF_ADDITEMS);		
			//修改明细
			 List<ReceiveItem> modifyItems = (List<ReceiveItem>) receiveItemMap.get(ConstantUtil.KEY_OF_MODIFYITEMS);
		    //总成本
			 BigDecimal amount = (BigDecimal) receiveItemMap.get(ConstantUtil.KEY_OF_AMOUNT);
			@Override
			public Object doInTransaction(TransactionStatus status) {
				JSONObject response=new JSONObject();
				receive.setAmount(amount);
				receive.setStatus(Receive.STATUS_TO_INVENTORY);
				receive.setSubmitter(sessionMessage.getUserId());
				//receive.setGmtSubmit(new Date());
				// 直接提交仓库,create操作：主表,修改的记录，新增记录
				if (receive.getId() == null) {
					if(receive.getOrdersId()!=null){
						//判断此引用订单是否已被其他人处理完毕
						ReceiveModel receiveAlready = getReceiveByOrdersId(receive.getOrdersId(),DictionaryEnum.GROUP_RECEIVE_STATUS.getGroup());						
						if(receiveAlready !=null){
							//JSONObject response = getReceiveAndItemsById(receiveAlready.getId(), sessionMessage);
							response.put(ConstantUtil.SUCCESS, false);
							response.put(ConstantUtil.MSG, ConstantUtil.MSG_AHEAD+receiveAlready.getSubmitterName()+ConstantUtil.MSG_ENDING);
							return response;
						}else{																		
							// 对新建的入库单，保存草稿，提交仓库，直接入库操作后清空orders的currentorId
							updatePurCurentorIdById(receive.getOrdersId());
						}						
					}
				    insertReceiveDraft(sessionMessage, receive,false);
				} else {
					response = checkCurrentorIdBeforeUpdate(sessionMessage, receive);
					if(response != null){
						return response;
					}else{
						// 已保存的入库单,update操作:主表,明细表，删除被删除的记录
						getDao().update(receive);
					}					
					if (modifyItems != null && modifyItems.size()>0){
						receiveItemDao.batchUpdateItems(modifyItems);
					}
					if (deleteItemIds != null && deleteItemIds.size()>0){
						batchDeleteItems(receive, deleteItemIds);
					}			
				}
				if (addItems != null && addItems.size()>0) {
					// 对新增的明细,不管入库单是否以创建，均为插入数据库
					addItems = setAddItemsReceiveId(addItems, receive);
					receiveItemDao.batchInsertItems(addItems);
				}	
				//页面返回信息
				response = getReceiveAndItemsById(receive.getId(), sessionMessage);				
				response.put(ConstantUtil.MSG, ConstantUtil.SAVE_SUBMIT_SUCCESS);
				response.put(ConstantUtil.SUCCESS, true);
			    return response;
			}
		});		
		return (JSONObject) result;
	}
	/**
	 * 入库
	 * @param queryParam
	 * @return {'success':true,'receiveObject':{'main':{xxxx},'details':[{xxx},{xxxxx}...],'buttons':{'isOwner':true/false,'buttons':[{xxxx},{xxxx}...]},'msg':{'confirm'/'alert':xxxxx}}}
	 *  "{'success':false,'errors':'发生异常'}";
	 */
	@SuppressWarnings("unchecked")
	public JSONObject backupInventory(String queryParam){
		final JSONObject receiveObj = JSONObject.fromObject(queryParam);
		final SessionMessage sessionMessage =UserHolder.getCurrentSessionMessage();
		Object result = transactionTemplate.execute(new TransactionCallback() {			
			//主表
			Receive receive = generateReceive(receiveObj);
			//明细表
			Map receiveItemMap = generateReceiveItem(receiveObj);		
			//删除明细
			List<Integer> deleteItemIds = generateDeleteItemIds(receiveObj);
			//新增明细
			List<ReceiveItem> addItems = (List<ReceiveItem>) receiveItemMap.get(ConstantUtil.KEY_OF_ADDITEMS);		
			//修改明细
			 List<ReceiveItem> modifyItems = (List<ReceiveItem>) receiveItemMap.get(ConstantUtil.KEY_OF_MODIFYITEMS);
		    //总成本
			 BigDecimal amount = (BigDecimal) receiveItemMap.get(ConstantUtil.KEY_OF_AMOUNT);
			@Override
			public Object doInTransaction(TransactionStatus status) {
				JSONObject response=new JSONObject();				
				if(receive.getId() == null){
					if(receive.getOrdersId()!=null){
						//判断此引用订单是否已被其他人处理完毕
						ReceiveModel receiveAlready = getReceiveByOrdersId(receive.getOrdersId(),DictionaryEnum.GROUP_RECEIVE_STATUS.getGroup());						
						if(receiveAlready !=null){
							//JSONObject response = getReceiveAndItemsById(receiveAlready.getId(), sessionMessage);
							response.put(ConstantUtil.SUCCESS, false);
							response.put(ConstantUtil.MSG, ConstantUtil.MSG_AHEAD+receiveAlready.getDepositerName()+ConstantUtil.MSG_ENDING);
							return response;
						}else{
							// 对新建的入库单，保存草稿，提交仓库，直接入库操作后清空orders的currentorId
							updatePurCurentorIdById(receive.getOrdersId());
						}
					}
					//订单直接入库
					handleReceiveInventory(sessionMessage, receive,amount);
					insertReceiveDraft(sessionMessage, receive,true);
				}else{
					response = checkCurrentorIdBeforeUpdate(sessionMessage, receive);
					if(response != null){
						return response;
					}
					handleReceiveInventory(sessionMessage, receive,amount);
				    // 已保存的入库单,update操作:主表,明细表，删除被删除的记录
				    getDao().update(receive);						
					if (modifyItems != null && modifyItems.size()>0){
						receiveItemDao.batchUpdateItems(modifyItems);
					}
					if (deleteItemIds != null && deleteItemIds.size()>0){
						batchDeleteItems(receive, deleteItemIds);
					}			
				}
				if (addItems != null && addItems.size()>0) {
					// 对新增的明细,不管入库单是否以创建，均为插入数据库
					addItems = setAddItemsReceiveId(addItems, receive);
					receiveItemDao.batchInsertItems(addItems);
				}	
				Integer partnerIdByBuyer = receive.getPartnerIdByBuyer();
				Partner partner = (Partner) partnerDao.getById(partnerIdByBuyer);
				// 保存库存表
				List<Inventory> inventories = generateInventory(receive,addItems,modifyItems,partner,sessionMessage);
				if (inventories !=null && inventories.size()>0)  {
					inventoryDao.batchInsertInventory(inventories);
				}
				
				// 保存零件属性表 , 插入报价表
				quotationService.handlePartPropertyAndQuotation(inventories,true);
								
				// 客户表里更新客户的应付款 ，应付款=原应付款+入库成本	
				BigDecimal unpaid = partner.getUnpaid();
				if(unpaid == null){
					unpaid = new BigDecimal(0);
				}
				partner.setUnpaid(unpaid.add(receive.getAmount()));
				partnerDao.updatePartnerAmountById(partner);
				// 生成应付款记录
				Payable payable = insertPayable(sessionMessage, receive,partnerIdByBuyer);	
				//更改采购订单状态
				if(receive.getOrdersId() != null){
					Map<String,Object> map = new HashMap<String,Object>();
					map.put("status", PurOrSaleOrder.STATUS_BUYER_ACPT);
					map.put("ordersId", receive.getOrdersId());
					map.put("buyerId", sessionMessage.getCompanyId());
					map.put("receivedId", receive.getId());
					purchaseOrderDao.updateOrdersStatusAndReceiveOrSaleId(map);
				}				
				//页面返回信息
			    response = getReceiveAndItemsById(receive.getId(), sessionMessage);				
				response.put(ConstantUtil.MSG, ConstantUtil.RECEIVE_DEPOSIT_SUCCESS);
				response.put(ConstantUtil.JSON_OF_PAYABLEID, payable.getId());
				response.put(ConstantUtil.JSON_OF_CUSTOMERID, payable.getCustomerId());
				response.put(ConstantUtil.SUCCESS, true);
			    return response;			    			
			}
		});
		return (JSONObject) result;
	}
	
	private void handleReceiveInventory(SessionMessage sessionMessage, Receive receive,BigDecimal amount) {
		receive.setAmount(amount);
		receive.setStatus(Receive.STATUS_INVENTORY);
		receive.setDepositer(sessionMessage.getUserId());
		if(receive.getSubmitter() == null){
			receive.setSubmitter(sessionMessage.getUserId());		
		}
		receive.setCurrentorId(null);
	}
	
	private Payable insertPayable( SessionMessage sessionMessage,Receive receive, Integer partnerIdByBuyer) {
		String code = codeGenericDao.getNewCode(sessionMessage.getCompanyId(),CodeGeneric.PAYABLE); // 应付款凭证号				
		Payable payable = new Payable();			
		payable.setCode(code);
		payable.setCompanyId(sessionMessage.getCompanyId());
		payable.setCustomerId(partnerIdByBuyer);
		payable.setDocumentType(Inventory.DOCUMENT_TYPE_RECEIVE);
		payable.setDocumentId(receive.getId());
		payable.setDocumentCode(receive.getCodeOfBuyer());
		payable.setPayable(receive.getAmount());
		payable.setCurrentorId(sessionMessage.getUserId());
		payable.setStatus(0);
		//payable.setGmtCreate(new Date());
		payable.setPaid(new BigDecimal(0));
		payableDao.createPayable(payable);	
		return payable;
	}

	
	/**
	 * 库存
	 * @param receive
	 * @param addItems
	 * @param modifyItems
	 * @param partner
	 * @return
	 */
    private List<Inventory> generateInventory(Receive receive, List<ReceiveItem> addItems,List<ReceiveItem> modifyItems,Partner partner,SessionMessage sessionMessage) {
		List<ReceiveItem> receiveItems =new ArrayList<ReceiveItem>();
		if (addItems != null && addItems.size()>0){
			receiveItems.addAll(addItems);
		}
		if (modifyItems != null && modifyItems.size()>0){
			receiveItems.addAll(modifyItems);
		}
	    List<Inventory> inventories =new ArrayList<Inventory>();
		if (receiveItems != null && receiveItems.size()>0) {
			for (ReceiveItem receiveItem : receiveItems) {
				Inventory inventory = new Inventory();
				//BeanUtil.copyProperties(inventory, receiveItem);
				BeanUtils.copyProperties(receiveItem, inventory, new String[]{"id"});
				
				inventory.setCompanyId(sessionMessage.getCompanyId());
				inventory.setInitQuantity(receiveItem.getQuantity());
				inventory.setOnHand(receiveItem.getQuantity());
				inventory.setDocumentType(Inventory.DOCUMENT_TYPE_RECEIVE);
				inventory.setDocumentId(receive.getId());
				inventory.setDocumentCode(receive.getCodeOfBuyer());
				inventory.setPartnerId(partner.getId());
				inventory.setPartnerName(partner.getName());
				inventory.setChangeQuantity(receiveItem.getQuantity());
				inventories.add(inventory);
			}
			return inventories;
		}
		return null;
	}

	/**
     * 设置新增明细的ReceiveId
     * @param addItems
     * @param receive
     * @return
     */
	private List<ReceiveItem> setAddItemsReceiveId(List<ReceiveItem> addItems,Receive receive) {
		List<ReceiveItem> receiveItems = new ArrayList<ReceiveItem>();
		for(ReceiveItem receiveItem : addItems){
			receiveItem.setReceiveId(receive.getId());
			receiveItems.add(receiveItem);
		}
		return receiveItems;
		
	}

	/**
	 * 解析前台删除明细的id
	 * @param receiveObj
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private List<Integer> generateDeleteItemIds(JSONObject receiveObj){
		// 被删除的记录的ID
		JSONArray deleteItemsIds = receiveObj.getJSONArray(ConstantUtil.KEY_OF_DELETEITEMIDS);
		List<Integer> deleteIds = new ArrayList<Integer>();
		if (deleteItemsIds != null && deleteItemsIds.size()>0) {
			deleteIds = (List) JSONArray.toCollection(deleteItemsIds);			
		}
		return deleteIds;
	}
	
    /**
     * 解析前台的明细信息，得到新增明细及修改明细，并计算总成本
     * @param receiveObj
     * @return
     */
	@SuppressWarnings("unchecked")
	private Map generateReceiveItem(JSONObject receiveObj) {
		//明细JSONArray
		JSONArray receiveArray = receiveObj.getJSONArray(ConstantUtil.JSON_OF_DETAILS);
		//被修改的明细
		List<ReceiveItem> modifyItems = new ArrayList<ReceiveItem>();
		//新增的明细
		List<ReceiveItem> addItems =  new ArrayList<ReceiveItem>();
		
		List<ReceiveItem> receiveItems = (List<ReceiveItem>) JSONArray.toCollection(receiveArray, ReceiveItem.class);
		BigDecimal totalAmount = new BigDecimal(0);
		if (receiveItems != null && receiveItems.size() >0) {
			for (ReceiveItem receiveItem : receiveItems) {
				if(receiveItem.getId() == null){
					//新增明细
					BigDecimal costAmount = receiveItem.getCost().multiply(new BigDecimal(receiveItem.getQuantity()));
					receiveItem.setCostAmount(costAmount);
					totalAmount = totalAmount.add(costAmount);
					//新增明细查找冗余信息
					Map map = new HashMap();
					map.put(ConstantUtil.PARAM_OF_CODE, receiveItem.getCode());
					map.put(ConstantUtil.PARAM_OF_SOURCE, receiveItem.getSource());
					Map part = partDao.getPartByConditionsJson(map);
					BeanUtil.populateBean(receiveItem, part);
					addItems.add(receiveItem);
				}else{
					//修改明细
					BigDecimal costAmount = receiveItem.getCost().multiply(new BigDecimal(receiveItem.getQuantity()));
					receiveItem.setCostAmount(costAmount);
					totalAmount = totalAmount.add(costAmount);
					modifyItems.add(receiveItem);
				}
			}
		}
		Map map = new HashMap();
		map.put(ConstantUtil.KEY_OF_ADDITEMS, addItems);
		map.put(ConstantUtil.KEY_OF_MODIFYITEMS, modifyItems);
		map.put(ConstantUtil.KEY_OF_AMOUNT, totalAmount);
		return map;
	}

	/**
	 * 将参数中的主表json对象解析成主表对象
	 * @param receiveJSON
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Receive generateReceive(JSONObject receiveObj){		
		JSONObject receiveJson = receiveObj.getJSONObject(ConstantUtil.JSON_OF_MAIN);	
		for(Iterator it=receiveJson.keys();it.hasNext();){
			Object key = it.next();
			Object value = receiveJson.get(key);	
			try {
				Field field = Receive.class.getDeclaredField(key.toString());				
				Class type = field.getType();
				if(Date.class.isAssignableFrom(type)&& StringUtils.isBlank(value.toString())){
					receiveJson.element(key.toString(), JSONNull.getInstance());
				}
			} catch (Exception e) {
				receiveJson.element(key.toString(), "");
			}
		}
		Receive receive = (Receive) JSONObject.toBean(receiveJson, Receive.class);
		if(receive.getId() != null){
			Receive receive2 = getRceiveById(receive.getId(),false);
			BeanUtils.copyProperties(receive2, receive,new String[]{"sellerId","partnerIdByBuyer","codeOfSeller","gmtAccept","memo"} );
		}		
		return receive;
	}
	/**
	 * 引用订单保存、提交、入库后清空order的currentorId
	 * @param orderId
	 */
	private void updatePurCurentorIdById( Integer orderId) {
		Map<String,Object> map = new HashMap<String,Object>();
		map.put(ConstantUtil.PARAM_OF_CURRENTORID,null);
		map.put("currentorName", null);
		map.put(ConstantUtil.PARAM_OF_ID, orderId);
		purchaseOrderDao.updatePurCurrentorIdById(map);
	}
	/**
	 * 单据保存前,判断是否为当前处理者所拥有
	 * @param sessionMessage
	 * @param currentorId
	 * @return {"success":false,"msg":'XXXXX'} or null
	 */
	private JSONObject checkCurrentorIdBeforeUpdate(SessionMessage sessionMessage, Receive receive) {
		Integer currentorId = receive.getCurrentorId();
		Integer userId =sessionMessage.getUserId();
		JSONObject jo = new JSONObject();
		String msg;		
		if(receive.getDepositer() != null && receive.getStatus().equals(Receive.STATUS_INVENTORY)){
			String depositorName = ((User)userDao.getById(receive.getDepositer())).getName();
			msg = ConstantUtil.MSG_AHEAD+depositorName+ConstantUtil.MSG_HAS_RECEIVE;
			jo.put(ConstantUtil.MSG, msg);
			jo.put(ConstantUtil.SUCCESS, false);
			return jo;
		}else if(currentorId !=null && !currentorId.equals(userId)){
			String currentorName = ((User)userDao.getById(currentorId)).getName();
		    msg = ConstantUtil.MSG_AHEAD+currentorName+ConstantUtil.MSG_ENDING_NOT;			
			jo.put(ConstantUtil.MSG, msg);
			jo.put(ConstantUtil.SUCCESS, false);
			return jo;
		}
		return null;
	}
	/**
	 * 根据入库单id删除入库单
	 * @param id
	 * @return {"success":false,"msg":'XXXXX'} or {"success":true}
	 */
	public JSONObject deleteReceiveById(Integer id) {
		Receive receive = getRceiveById(id,false);		
		JSONObject response = checkCurrentorIdBeforeUpdate(UserHolder.getCurrentSessionMessage(), receive);
		if(response != null){
			return response;
		}
	    boolean success = deleteReceiveByReceiveId(id);
	    JSONObject resp = new JSONObject();
		if(!success){
			resp.put(ConstantUtil.SUCCESS, false);
			resp.put(ConstantUtil.MSG, ConstantUtil.MSG_DRAFT_NOT_EXIST);
		}else{
			resp.put(ConstantUtil.SUCCESS, true);
			resp.put(ConstantUtil.MSG, ConstantUtil.MSG_DELETE_DRAFT_SUCCESS);
		}
		return resp;
		
		
	}
	public void setReceiveItemDao(IReceiveItemDao receiveItemDao) {
		this.receiveItemDao = receiveItemDao;
	}

	public void setInventoryDao(IInventoryDao inventoryDao) {
		this.inventoryDao = inventoryDao;
	}
	
	public void setPartnerDao(IPartnerDao partnerDao) {
		this.partnerDao = partnerDao;
	}

	public void setPayableDao(IPayableDao payableDao) {
		this.payableDao = payableDao;
	}

	public void setPurchaseOrderDao(IPurchaseOrderDao purchaseOrderDao) {
		this.purchaseOrderDao = purchaseOrderDao;
	}

	public void setCodeGenericDao(ICodeGenericDao codeGenericDao) {
		this.codeGenericDao = codeGenericDao;
	}

	public void setUserDao(IUserDao userDao) {
		this.userDao = userDao;
	}

	public void setEngineAccess(EngineAccess engineAccess) {
		this.engineAccess = engineAccess;
	}

	public void setPartDao(IPartDao partDao) {
		this.partDao = partDao;
	}

	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	public void setPurchaseOrderDetailDao(
			IPurchaseOrderDetailDao purchaseOrderDetailDao) {
		this.purchaseOrderDetailDao = purchaseOrderDetailDao;
	}

	public void setQuotationService(QuotationService quotationService) {
		this.quotationService = quotationService;
	}

	@SuppressWarnings("unchecked")
	public JSONObject acceptOrderToReceiveByOrderId(Integer orderId) {
		SessionMessage sm = UserHolder.getCurrentSessionMessage();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("currentorId", sm.getUserId());
		map.put("currentorName", sm.getUserName());
		map.put("id", orderId);
		map.put("buyerId", sm.getCompanyId());
		boolean success = purchaseOrderDao.updatePurCurrentorIdById(map);		
		JSONObject response = new JSONObject();	
		if(success){
			// 封装主表信息
			Map mainMap = purchaseOrderDao.getOrderByIdJson(orderId);
			//mainJson = JSONObject.fromObject(mainMap);
			// 封装明细表信息
			List<Map<String, String>> detailMap = purchaseOrderDetailDao.getPurchaseOrderDetailByOrderIdJson(orderId);			
			//detailJson = JSONArray.fromObject(detailMap);						
			response.put("order",mainMap );
			response.put("orderItem", detailMap);
			response.put(ConstantUtil.SUCCESS, true);				
		}else{
			response.put(ConstantUtil.SUCCESS, false);
			response.put(ConstantUtil.MSG,ConstantUtil.QUOTE_OREDERS_FAILURE);				
		}
		return response;
	}
	

}
